/**********************************************************************//**
 @file main.cpp 
 @brief Contains Main function and glut callback functions
 @author Ricardo C. Marques <rmarques@inf.puc-rio.br>
 @version 0.0.1
 @date 05/11/2012
**************************************************************************/
   
// Standard Libraries
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#undef   _CRT_SECURE_NO_WARNINGS

// Graphic Libraries
#define GLUT_DISABLE_ATEXIT_HACK
#include "GL/glut.h"
#undef  GLUT_DISABLE_ATEXIT_HACK

// Auxiliary Header Files
#include "draw.hpp"
#include "manip.hpp"
#include "ptcloud.hpp"


// Constants
#define MESH_FILENAME   "../data/vale_2.txt"
#define WINDOW_WIDTH    600 
#define WINDOW_HEIGHT   600
#define ESC_KEY          27

// GLUT Callback Functions
static void Keyboard(unsigned char key, int , int )
{
    if( key=='q' || key=='Q' || key==ESC_KEY)
        exit(1);
    else if( key=='a' || key=='A' )
        ChangeAxisDisplayMode();
    else if( key=='g' || key=='G' )
        ChangeGridDisplayMode();       
	
    glutPostRedisplay();
}

static void SpecialKeys(int key, int , int  )
{
    if( key==GLUT_KEY_LEFT )
        ShiftLeft();
    else if( key==GLUT_KEY_RIGHT )
        ShiftRight();
    else if( key==GLUT_KEY_UP )
        ShiftUp();
    else if( key==GLUT_KEY_DOWN )
        ShiftDown();
    else if( key==GLUT_KEY_PAGE_DOWN )
        ZoomIn();
    else if( key==GLUT_KEY_PAGE_UP )
        ZoomOut();

    glutPostRedisplay();
}
static void MouseClick(int button, int state, int x, int y)
{
    // Manipulation Operations
    {
        if( button==GLUT_LEFT_BUTTON )
        {
            if( state==GLUT_DOWN )
            {           
                //printf("Left Button Pressed\n");
                //printf("x=%d y=%d\n", x, y);
                StartZoom(x,y);
                return; // Avoid displaying this event
            }
            else // GLUT_UP
            {           
                //printf("Left Button Released\n");
			    //printf("x=%d y=%d\n", x, y);
                EndZoom(x,y);
            }
        }
        else if( button==GLUT_RIGHT_BUTTON )
        {
            if( state==GLUT_DOWN )
                RestoreLastZoom();
        }
        else if( button==GLUT_MIDDLE_BUTTON )
        {
            if( state==GLUT_DOWN )
            {           
                //printf("Middle Button Pressed\n");
                //printf("x=%d y=%d\n", x, y);
                StartPanning(x,y);
            }
            else // GLUT_UP
            {            
                //printf("Middle Button Released\n");
			    //printf("x=%d y=%d\n", x, y);
                EndPanning(x,y);
            }
        }
        else if( button==GLUT_WHEEL_DOWN && state==GLUT_UP )
            ZoomIn();
        else if( button==GLUT_WHEEL_UP && state==GLUT_UP )
            ZoomOut();
    }

    glutPostRedisplay();
}
static void Display(void)
{
    glClearColor(0.f,0.f,0.f,1.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    DisplayCanvas();

    glFlush();
    glutSwapBuffers();
}
static void init()
{
    const char* filename = MESH_FILENAME;
    PointCloud* ptcloud = new PointCloud(filename);
    Point2D A,B,C;
    ptcloud->GetBoundingTri(&A,&B,&C);
    delete(ptcloud);
}
// Main Function
int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

    glutInitWindowSize(WINDOW_WIDTH , WINDOW_HEIGHT );
    glutInitWindowPosition( (glutGet(GLUT_SCREEN_WIDTH )-WINDOW_WIDTH )/2, 
                            (glutGet(GLUT_SCREEN_HEIGHT)-WINDOW_HEIGHT)/2   );
    glutCreateWindow("INF2604 - Trabalho Final");

	glutDisplayFunc (Display);
	glutKeyboardFunc(Keyboard);
    glutSpecialFunc (SpecialKeys);
	glutMouseFunc   (MouseClick);
	//glutMotionFunc  (MouseDrag); // defined at manip.cpp
    //glutPassiveMotionFunc(NULL); // defined at edit.cpp

    glutIgnoreKeyRepeat(true);

    init();

	glutMainLoop();
	return 0;
}